package logic

import (
	"api/model/discountmember"
	order2 "api/model/order"
	"api/service"
	"api/utils"
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"math"
	"strconv"
	"strings"

	"api/internal/svc"
	"api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type DiffCardBalanceLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewDiffCardBalanceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DiffCardBalanceLogic {
	return &DiffCardBalanceLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 【用户】 折扣卡余额抵扣
func (l *DiffCardBalanceLogic) DiffCardBalance(req *types.RequestDiffCardBalance) (resp *types.ResponseMsg, err error) {
	// 获取单号
	conn := sqlx.NewMysql(l.svcCtx.Config.DataSource)
	redis := l.svcCtx.RedisPool.Get()
	defer redis.Close()

	discountMemberModel := discountmember.NewDiscountMemberModel(conn)

	orderModel := order2.NewOrderModel(conn)
	order, _ := orderModel.FindOne(l.ctx, req.TradeNo)

	// 加锁
	commonService := service.NewCommonService(l.ctx, l.svcCtx)
	lockName := "lock:" + req.TradeNo
	lockId, err := commonService.Lock(redis, lockName, 2, 2)

	// 解锁
	defer commonService.ReleaseLock(redis, lockName, lockId)

	// 判断余额
	openId := ""
	if req.WxOpenId != "" {
		openId = req.WxOpenId
	} else if req.AliOpenId != "" {
		openId = req.AliOpenId
	} else {
		return &types.ResponseMsg{
			Msg:  "网络异常,请稍后重试",
			Code: 200,
		}, nil
	}
	list, _ := discountMemberModel.ListByBusId(l.ctx, int64(order.BusinessId), openId)
	var id int64
	var values float64
	var emptyIds []int64
	var balance int64 // 扣减后余额

	// 计算方式  不足则余额抵扣
	var count = float64(order.Amount)

	for _, item := range *list {
		// 待扣减金额
		values = values + float64(item.Balance)*(1+float64(100-item.Discount)/100) // 实际能产生的支付资金

		if values >= float64(order.Amount) {
			balance = item.Balance - int64(math.Floor(count*float64(item.Discount)/100))
			id = item.Id

			break

		} else {
			// 不够扣减的 balance直接置为 0
			emptyIds = append(emptyIds, item.Id)
			count = count - float64(item.Balance)

		}

	}

	if id == 0 {
		return &types.ResponseMsg{
			Msg:  "余额不足",
			Code: 200,
		}, nil
	}

	// 开启事务
	err = conn.TransactCtx(context.Background(), func(ctx context.Context, session sqlx.Session) error {

		// 余额修改
		if len(emptyIds) > 0 {
			str := ""
			strNums := make([]string, len(emptyIds))
			for i, num := range emptyIds {
				strNums[i] = strconv.Itoa(int(num))
			}

			// 使用逗号连接字符串切片
			result := strings.Join(strNums, ",")

			if req.WxOpenId != "" {
				str = fmt.Sprintf("update  `discount_member` set `balance` = 0 ,update_at = ?  where `wx_open_id` = %s  and id in (%s)", req.WxOpenId, result)
			} else {
				str = fmt.Sprintf("update  `discount_member` set `balance` = 0 ,update_at = ? where `ali_open_id` = %s  and id in (%s)", req.AliOpenId, result)
			}

			stmt, _ := session.Prepare(str)

			_, err := stmt.ExecCtx(ctx, utils.GetCurDateTime())
			if err != nil {
				return err
			}

		}

		str := ""
		if req.WxOpenId != "" {
			str = fmt.Sprintf("update  `discount_member` set `balance` = ?,update_at = ? where `wx_open_id` = %s  and id = ? ", req.WxOpenId)
		} else {
			str = fmt.Sprintf("update  `discount_member` set `balance` = ?,update_at = ? where `ali_open_id` = %s  and id = ? ", req.AliOpenId)
		}

		stmt, _ := session.Prepare(str)

		_, err := stmt.ExecCtx(ctx, balance, utils.GetCurDateTime(), id)

		if err != nil {
			return err
		}

		// 修改交易订单状态

		stmt, _ = session.Prepare("update  `order` set `status` = ?,update_at = ? where  trade_no = ? ")

		_, err = stmt.ExecCtx(ctx, service.ORDER_SUCCESS, utils.GetCurDateTime(), req.TradeNo)

		if err != nil {
			return err
		}

		return nil
	})

	if err != nil {
		fmt.Println(err.Error())
		return &types.ResponseMsg{
			Msg:  "网络异常,请稍后重试",
			Code: 200,
		}, nil
	}

	//socket := l.svcCtx.WebSocketPool.Get()
	//busService := service.NewBusinessService(l.ctx, l.svcCtx)
	//business := busService.GetBussById(redis, order.BusinessId)
	//
	//fd, err := busService.GetBussSocket(redis, business.Phone)
	//if err == nil {
	//
	//	result, _ := fmt.Printf("%.2f元\n", float64(order.Amount)/float64(100))
	//	d := map[string]string{
	//		"voice": "会员卡扣款" + strconv.Itoa(result), // 扣款信息
	//	}
	//
	//	jsonD, _ := json.Marshal(d)
	//
	//	data := map[string]string{
	//		"to_id": fd,
	//		"data":  string(jsonD),
	//		"code":  "sendMsg",
	//	}
	//
	//	jsonD, _ = json.Marshal(data)
	//	err = socket.WriteMessage(websocket.TextMessage, jsonD)
	//}

	return &types.ResponseMsg{
		Msg:  "成功",
		Code: 200,
	}, nil

}
